package com.fanghuaiming.test.c4.多路复用;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

/****
 * @description:
 * @version:1.0.0
 * @author fanghuaiming
 * @data Created in 2021/9/21 下午10:47
 *
 */
public class WriteServer {

  public static void main(String[] args) throws IOException {
      ServerSocketChannel ssc = ServerSocketChannel.open();
      ssc.configureBlocking(false);

      Selector selector = Selector.open();
      ssc.register(selector, SelectionKey.OP_ACCEPT);

      ssc.bind(new InetSocketAddress(8080));

      while (true){
          selector.select();
          Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
          while (iterator.hasNext()){
              SelectionKey key = iterator.next();
              iterator.remove();
              if (key.isAcceptable()) {
                  SocketChannel sc = ssc.accept();
                  sc.configureBlocking(false);
                  SelectionKey scKey = sc.register(selector, 0, null);
                  scKey.interestOps(SelectionKey.OP_READ);
                  //1.向客户端发送大量数据
                  StringBuilder sb = new StringBuilder();
                  for (int i = 0; i < 30000000; i++){
                      sb.append("a");
                  }
                  ByteBuffer buffer = Charset.defaultCharset().encode(sb.toString());
                  //2.返回值代表实际写入的字节数
                  int write = sc.write(buffer);
                  System.out.println(write);
                  //3.判断是否有剩余内容
                  if (buffer.hasRemaining()){
                      //4.关注可写事件(原本的关注事件加本次的关注事件)
                      scKey.interestOps(scKey.interestOps() + SelectionKey.OP_WRITE);
                      //5.要把未写完的数据挂到sckey上
                      scKey.attach(buffer);
                  }
              }else if(key.isWritable()){
                  ByteBuffer buffer = (ByteBuffer) key.attachment();
                  SocketChannel sc = (SocketChannel) key.channel();
                  int write = sc.write(buffer);
                  System.out.println(write);
                  //6.清理操作(如果没有数据可写了)
                  if(!buffer.hasRemaining()){
                      key.attach(null);//清除bytebuffer
                      key.interestOps(key.interestOps() - SelectionKey.OP_WRITE);//不需要再关注可写事件
                  }
              }
          }
      }
  }
}
